﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LCA.Community.Web.Filters;
using Microsoft.Practices.Unity;
using LCA.Community.DAL.Interfaces;
using LCA.Community.DAL.Model;
using LCA.Community.Web.Models;

namespace LCA.Community.Web.Controllers
{
    public class FriendshipController : BaseController
    {
        /// <summary>
        /// Action for showing the friends of a user
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <returns>View showing the friends of a user.</returns>
        [SecurityFilter(SecurityRequisites = "Owner,Friend", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        [ErrorFilter(typeof(Exception), "Se produjo un error al procesar la solicitud", 1)]
        [ErrorFilter(typeof(NullReferenceException), "El usuario referenciado no existe", 2)]
        public ActionResult Index(string id)
        {
            var user = UsersRepository.Get(id);
            if (user == null)
                throw new NullReferenceException();

            var userViewModel = MvcApplication.Container.Resolve<UserViewModel>(new ParameterOverrides { { "user", user } }); ;
            ViewData["owner"] = IsOwner(id);
            ViewData["friends"] = IsFriend(id);
            ViewData["username"] = id;
            return View("Index", userViewModel);
        }

        /// <summary>
        /// Action for removing the friends of a user.
        /// </summary>
        /// <param name="selectedusers">The friends to remove.</param>
        /// <returns>Partial view with the friends of the user.</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ErrorFilter(typeof(Exception), "Se produjo un error al procesar la solicitud", 1)]
        [ErrorFilter(typeof(NullReferenceException), "El usuario referenciado no existe", 2)]
        public ActionResult RemoveFriends(String[] selectedusers)
        {
            if(selectedusers != null)
                foreach (string friendID in selectedusers)
                    FriendshipsRepository.Delete(friendID, UserID);

            var partialView = new PartialViewResult();
            partialView.ViewName = "ShowUsers";
            partialView.ViewData.Model = UsersRepository.GetUserFriends(UserID);
            partialView.ViewData["owner"] = IsOwner(UserID);
            return partialView;
        }

        /// <summary>
        /// Action for requesting friendship.
        /// </summary>
        /// <param name="id">The friend id.</param>
        /// <returns>View of the user index.</returns>
        [SecurityFilter(SecurityRequisites = "Registered", ErrorResource = "NotLoggedIn")]
        [ErrorFilter(typeof(Exception), "Se produjo un error al procesar la solicitud", 1)]
        [ErrorFilter(typeof(NullReferenceException), "El usuario o amigo referenciado no existe", 2)]
        public ActionResult InviteFriend(string id)
        {
            if (MessagesRepository.GetFriendshipRequestMessage(UserID,id) == null)
            {
                var message = CreateFriendshipRequestMessage(id);
                MessagesRepository.Add(message);
            }
            return RedirectToAction("Index", "User", new { id = id });
        }

        /// <summary>
        /// Action for accepting a friendship request.
        /// </summary>
        /// <param name="id">The friend id.</param>
        /// <returns>View of the mailbox of the user.</returns>
        [ErrorFilter(typeof(Exception), "Se produjo un error al procesar la solicitud", 1)]
        [ErrorFilter(typeof(NullReferenceException), "El usuario o amigo referenciado no existe", 2)]
        public ActionResult AcceptFriendshipRequest(string id)
        {
            var requestMessage = MessagesRepository.GetFriendshipRequestMessage(id, UserID);
            if(requestMessage != null)
            {
                var message = CreateFriendshipAcceptedMessage(id);

                MessagesRepository.Delete(requestMessage);
                MessagesRepository.Add(message);

                FriendshipsRepository.Add(id,UserID);
            }

            return RedirectToAction("Index", "Mailbox", new { id = UserID });
        }

        /// <summary>
        /// Action for denying a friendship request.
        /// </summary>
        /// <param name="id">The friend id.</param>
        /// <returns>View of the mailbox of the user.</returns>
        [ErrorFilter(typeof(Exception), "Se produjo un error al procesar la solicitud", 1)]
        [ErrorFilter(typeof(NullReferenceException), "El usuario o amigo referenciado no existe", 2)]
        public ActionResult DenyFriendshipRequest(string id)
        {
            var requestMessage = MessagesRepository.GetFriendshipRequestMessage(id, UserID);
            if (requestMessage != null)
            {
                var message = CreateFriendshipDeniedMessage(id);

                MessagesRepository.Delete(requestMessage);
                MessagesRepository.Add(message);
            }

            return RedirectToAction("Index", "Mailbox", new { id = UserID });
        }

        #region Private methods
        /// <summary>
        /// Creates a friendship request message.
        /// </summary>
        /// <param name="friendId">The friend id.</param>
        /// <returns>Friendship request message</returns>
        public Message CreateFriendshipRequestMessage(string friendId)
        {
            string acceptLink = string.Format("<a href={0}>aquí<a />", Url.Action("AcceptFriendshipRequest", "Friendship", new { id = UserID }));
            string denyLink = string.Format("<a href={0}>aquí<a />", Url.Action("DenyFriendshipRequest", "Friendship", new { id = UserID }));
            string body = string.Format("El usuario {0} quiere ser tu amigo. Haz click {1} para aceptar o {2} para denegar.", friendId, acceptLink, denyLink);
            string subject = MessagesRepository.FriendshipRequestSubject;
            return new Message(UserID, subject, body, new List<string> { friendId });
        }

        /// <summary>
        /// Creates a friendship accepted message.
        /// </summary>
        /// <param name="friendId">The friend id.</param>
        /// <returns>Friendship accepted message.</returns>
        public Message CreateFriendshipAcceptedMessage(string friendId)
        {
            string body = string.Format("El usuario {0} ha aceptado tu invitación de amistad.", UserID);
            string subject = string.Format("Solicitud de amistad aceptada.");
            return new Message(UserID, subject, body, new List<string> { friendId });
        }

        /// <summary>
        /// Creates a friendship denied message.
        /// </summary>
        /// <param name="friendId">The friend id.</param>
        /// <returns>Friendship denied message</returns>
        public Message CreateFriendshipDeniedMessage(string friendId)
        {
            string body = string.Format("El usuario {0} ha denegado tu petición de amistad.", UserID);
            string subject = string.Format("Solicitud de amistad denegada");
            return new Message(UserID, subject, body, new List<string> { friendId });
        }
        #endregion

        [Dependency]
        public IUsersRepository UsersRepository { get; set; }
        [Dependency]
        public IMessagesRepository MessagesRepository { get; set; }
    }
}
